﻿using FluentValidation;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Service.Framework;
using Service.Framework.Packet;
using Service.Framework.Utils;

namespace Service.Core.Filters
{
    /// <summary>
    /// 全局异常捕获过滤器
    /// </summary>
    public class GlobalExceptionFilter : IAsyncExceptionFilter
    {
        private readonly ILogger<GlobalExceptionFilter> _logger;

        /// <summary>
        /// 
        /// </summary>
        public GlobalExceptionFilter(ILogger<GlobalExceptionFilter> logger)
        {
            _logger = logger;
        }

        /*
         为什么对于未知的异常要输出 Http 500，而对于业务逻辑的异常，建议输出 Http 200？

        因为监控系统实际上会对 Http 的响应码进行识别，当监控系统识别到 Http 响应是 500 的比例比较高的情况下，会认为系统的可用性有问题。
        这个时候告警系统就会发出警告。
         */
        public Task OnExceptionAsync(ExceptionContext context)
        {
            //获取日志记录组件
            //ILoggerManager logger = context.HttpContext.RequestServices.GetService(typeof(ILoggerManager)) as ILoggerManager;
            IKnownException knownException = context.Exception as IKnownException;
            ValidationException validationException = context.Exception as ValidationException;
            if (knownException != null) //用户故意引发的异常
            {
                context.Result = new JsonResult(R.ResultMessage(knownException.StatusCode, knownException.Mesaage),
                    JsonSerializeUtil.DefaulSerializeSetting);
                context.HttpContext.Response.StatusCode = (Int32)System.Net.HttpStatusCode.OK; //200
            }
            else //真异常
            {
                _logger.LogError(context.Exception, "全局异常");
                String errorMessage =
                    $"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:sss")} 异常消息：{context.Exception.ToString()}";
                _logger.LogError(errorMessage);
#if DEBUG
                context.Result = new JsonResult(R.Error(context.Exception.ToString(),""),
                    JsonSerializeUtil.DefaulSerializeSetting);
#endif

#if RELEASE
                context.Result =
 new JsonResult(R.ErrorMessage("系统服务出现异常，请联系管理员"), JsonSerializeUtil.DefaulSerializeSetting);
#endif
                context.HttpContext.Response.StatusCode = (Int32)System.Net.HttpStatusCode.InternalServerError; //500
            }

            return Task.CompletedTask;
        }
    }
}